package com.kingyea.mobilepolice.util;


import com.alibaba.fastjson.JSON;
import com.kingyea.mobilepolice.system.Result;
import org.springframework.http.*;
import org.springframework.security.crypto.codec.Base64;
import org.springframework.web.client.RestTemplate;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * @author Mr.Lin
 * @version v1.0.0
 * @description
 * @date Created in 2018/2/10 10:51
 */
public class HttpUtil {

    /**
     * logger
     */

    private static String CHARSET_UTF8 = GlobalVar.CHARSET_UTF8;

    private static Integer CONNECT_TIMEOUT = 30000;

    private static Integer REAS_TIMEOUT = 30000;


    /**
     * POST方法提交Http请求
     * 注意：Http方法中只有POST方法才能使用body来提交内容
     *
     * @param url     资源路径（如果url中已经包含参数，则params应该为null）
     * @param params  参数
     * @param headers 请求头属性 {"Connection":"Keep-Alive","Content-Type":"application/json或者application/x-www-form-urlencoded"}
     * @param method  请求方法
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static String invokeUrl(String url, Map params, Map<String, String> headers, HttpMethod method) {
        return invokeUrl(url, params, headers, method, CHARSET_UTF8);
    }

    /**
     * POST方法提交Http请求
     * 注意：Http方法中只有POST方法才能使用body来提交内容
     *
     * @param url     资源路径（如果url中已经包含参数，则params应该为null）
     * @param params  参数
     * @param headers 请求头属性 {"Connection":"Keep-Alive","Content-Type":"application/json或者application/x-www-form-urlencoded"}
     * @param method  请求方法
     * @param charset 字符集（一般该为“utf-8”）
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static String invokeUrl(String url, Map params, Map<String, String> headers, HttpMethod method, String charset) {
        return invokeUrl(url, params, headers, method, charset, CONNECT_TIMEOUT, REAS_TIMEOUT);
    }

    /**
     * POST方法提交Http请求
     * 注意：Http方法中只有POST方法才能使用body来提交内容
     *
     * @param url            资源路径（如果url中已经包含参数，则params应该为null）
     * @param params         参数
     * @param headers        请求头属性 {"Connection":"Keep-Alive","Content-Type":"application/json或者application/x-www-form-urlencoded"}
     * @param method         请求方法
     * @param charset        字符集（一般该为“utf-8”）
     * @param connectTimeout 连接超时时间（单位为ms）
     * @param readTimeout    读取超时时间（单位为ms）
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static String invokeUrl(String url, Map params, Map<String, String> headers, HttpMethod method
            , String charset, int connectTimeout, int readTimeout) {
        // 构造 请求参数的字符串
        String paramsStr = "";
        if (params != null) {

            if (headers != null && headers.entrySet().stream().anyMatch(map -> map.getKey().equalsIgnoreCase("Content-Type") && map.getValue().toUpperCase().contains("JSON"))) {
                // Content-Type 为 JSON格式
                paramsStr = JSON.toJSONString(params);
            } else {
                StringBuilder paramsStrBuilder = new StringBuilder();
                Set<Map.Entry> entries = params.entrySet();
                for (Map.Entry entry : entries) {
                    String value = (entry.getValue() != null) ? (String.valueOf(entry.getValue())) : "";
                    try {
                        paramsStrBuilder.append(entry.getKey() + "=" + URLEncoder.encode(value, CHARSET_UTF8) + "&");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }
                paramsStr = paramsStrBuilder.toString();
                if (paramsStr.endsWith("&")) {
                    paramsStr = paramsStr.substring(0, paramsStr.lastIndexOf("&"));
                }
                // get 方法的就把参数拼接到url后面
                if (method.equals(HttpMethod.GET) && !org.springframework.util.StringUtils.isEmpty(paramsStr)) {
                    if (!url.contains("?")) {
                        url += "?" + paramsStr;
                    } else {
                        url += "&" + paramsStr;
                    }
                }
            }
        }

        URL uUrl;
        HttpURLConnection conn = null;
        BufferedWriter out = null;
        BufferedReader in = null;
        try {
            // 创建和初始化连接
            uUrl = new URL(url);
            conn = (HttpURLConnection) uUrl.openConnection();
            // 指定请求header参数
            if (headers != null && headers.size() > 0) {
                Set<String> headerSet = headers.keySet();
                for (String key : headerSet) {
                    conn.setRequestProperty(key, headers.get(key));
                }
            }
            conn.setRequestMethod(method.toString());
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 设置连接超时时间
            conn.setConnectTimeout(connectTimeout);
            // 设置读取超时时间
            conn.setReadTimeout(readTimeout);

            if (!org.springframework.util.StringUtils.isEmpty(paramsStr) && method != HttpMethod.GET) {
                // 发送请求参数
                out = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), charset));
                out.write(paramsStr);
                out.flush();
            }

            //接收返回结果
            StringBuilder result = new StringBuilder();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
            if (in != null) {
                String line = "";
                while ((line = in.readLine()) != null) {
                    result.append(line);
                }
            }
            return result.toString();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("调用接口[" + url + "]失败！请求URL：" + url + "，参数：" + params);
            //处理错误流
            try {
                byte[] buf = new byte[100];
                InputStream errorStream = conn.getErrorStream();
                if (errorStream != null) {
                    StringBuilder errorResult = new StringBuilder();
                    while (errorStream.read(buf) > 0) {
                        errorResult.append(new String(buf));
                    }
                    System.out.println("服务器返回错误信息：" + errorResult.toString());
                    errorStream.close();
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //关闭连接
            if (conn != null) {
                conn.disconnect();
            }
        }
        return null;
    }


    public static void main(String[] args) {

        test();

        String url = "http://localhost:8782/test";

        String author = "Basic " + Base64.encode(("admin" + ":" + "123").getBytes());

        Map<String, String> headers = new HashMap<String, String>() {{
            put("Content-Type", "application/json");
            put("Authorization", author);
            put("token", "tom_token");
        }};

        Map<String, Object> params = new HashMap<String, Object>() {{
            put("param1", "中文");
            put("param2", "english");
        }};

        Map params_json = JSON.parseObject("{\"id\":6,\"name\":\"tom6\",\"num\":999}", Map.class);


        String str2 = HttpUtil.invokeUrl(url, params_json, headers, HttpMethod.PUT);
        System.out.println(str2);

        str2 = HttpUtil.invokeUrl(url, params, new HashMap<String, String>() {{
            put("Authorization", author);
            put("token", "tom_token");
        }}, HttpMethod.GET);
        System.out.println(str2);

        str2 = HttpUtil.invokeUrl(url, params_json, headers, HttpMethod.POST);
        System.out.println(str2);


        String content = "src: local{'Open Sans Light'}, local{'OpenSans-Light'}, url(http://fonts.gstatic.com/s/opensans/v13/DXI1ORHCpsQm3Vp6mXoaTa-j2U0lmluP9RWlSytm3ho.woff2) format('woff2')";
        // 从内容上截取路径数组
//        Pattern pattern = Pattern.compile("(?<=\\()[^\\)]+");
        Pattern pattern = Pattern.compile("(?<=\\{)[^\\}]+");
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            System.out.println(matcher.group());
        }
    }


    private static void test() {
        String url = "http://localhost:8782/serviceInfo/searchByCondition";
        RestTemplate client = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
//  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
//  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        Map<String, Object> params = new HashMap<>();
//  也支持中文
        params.put("username", "用户名");
        params.put("password", "123456");
        params.put("pageSize", 2);

        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<Map<String, Object>>(params, headers);
//        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(params, headers);// 表单 MULTIPART_FORM_DATA 的时候 ，参数用MultiValueMap 来封装
//  执行HTTP请求
        ResponseEntity response = client.exchange(url, HttpMethod.POST, requestEntity, Result.class);
//  输出结果
        System.out.println(response.getBody());
        System.out.println();
    }


}
